#ifndef _GPT_H
#define _GPT_H

#define MSDOS_MBR_SIGNATURE 0xAA55
#define EFI_PMBR_OSTYPE_EFI 0xEF
#define EFI_PMBR_OSTYPE_EFI_GPT 0xEE

#define GPT_HEADER_SIGNATURE 0x5452415020494645ULL
#define GPT_HEADER_REVISION_V1 0x00010000
#define GPT_PRIMARY_PARTITION_TABLE_LBA 1ULL
#define GPT_ENTRY_NAME "gpt"
#define GPT_ENTRY_NUMBERS        128
#define GPT_ENTRY_SIZE            128
#define PART_PROPERTY_BOOTABLE (1 << 2)

#define EFI_GUID(a,b,c,d0,d1,d2,d3,d4,d5,d6,d7) \
    ((efi_guid_t) \
    {{ (a) & 0xff, ((a) >> 8) & 0xff, ((a) >> 16) & 0xff, ((a) >> 24) & 0xff, \
        (b) & 0xff, ((b) >> 8) & 0xff, \
        (c) & 0xff, ((c) >> 8) & 0xff, \
        (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) }})

#define PARTITION_IDBLOCK_GUID \
    EFI_GUID(0xDA2BB095, 0x390E, 0x48ca, \
        0x90, 0x47, 0x05, 0xE8, 0x18, 0xB2, 0x97, 0xCE)

typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int  u32;
typedef unsigned long long u64;

#define uswap_16(x) \
    ((((x) & 0xff00) >> 8) | \
     (((x) & 0x00ff) << 8))
#define uswap_32(x) \
    ((((x) & 0xff000000) >> 24) | \
     (((x) & 0x00ff0000) >>  8) | \
     (((x) & 0x0000ff00) <<  8) | \
     (((x) & 0x000000ff) << 24))
#define _uswap_64(x, sfx) \
    ((((x) & 0xff00000000000000##sfx) >> 56) | \
     (((x) & 0x00ff000000000000##sfx) >> 40) | \
     (((x) & 0x0000ff0000000000##sfx) >> 24) | \
     (((x) & 0x000000ff00000000##sfx) >>  8) | \
     (((x) & 0x00000000ff000000##sfx) <<  8) | \
     (((x) & 0x0000000000ff0000##sfx) << 24) | \
     (((x) & 0x000000000000ff00##sfx) << 40) | \
     (((x) & 0x00000000000000ff##sfx) << 56))
#if defined(__GNUC__)
# define uswap_64(x) _uswap_64(x, ull)
#else
# define uswap_64(x) _uswap_64(x, )
#endif
#define __LITTLE_ENDIAN__ 1
#ifdef __LITTLE_ENDIAN__
# define cpu_to_le16(x)        (x)
# define cpu_to_le32(x)        (x)
# define cpu_to_le64(x)        (x)
# define le16_to_cpu(x)        (x)
# define le32_to_cpu(x)        (x)
# define le64_to_cpu(x)        (x)
# define cpu_to_be16(x)        uswap_16(x)
# define cpu_to_be32(x)        uswap_32(x)
# define cpu_to_be64(x)        uswap_64(x)
# define be16_to_cpu(x)        uswap_16(x)
# define be32_to_cpu(x)        uswap_32(x)
# define be64_to_cpu(x)        uswap_64(x)
#else
# define cpu_to_le16(x)        uswap_16(x)
# define cpu_to_le32(x)        uswap_32(x)
# define cpu_to_le64(x)        uswap_64(x)
# define le16_to_cpu(x)        uswap_16(x)
# define le32_to_cpu(x)        uswap_32(x)
# define le64_to_cpu(x)        uswap_64(x)
# define cpu_to_be16(x)        (x)
# define cpu_to_be32(x)        (x)
# define cpu_to_be64(x)        (x)
# define be16_to_cpu(x)        (x)
# define be32_to_cpu(x)        (x)
# define be64_to_cpu(x)        (x)
#endif


typedef union {
    struct {
    unsigned int time_low;
    unsigned short time_mid;
    unsigned short time_hi_and_version;
    unsigned char clock_seq_hi_and_reserved;
    unsigned char clock_seq_low;
    unsigned char node[6];
    } uuid;
    u8 raw[16];
} efi_guid_t;
#pragma pack(1)
typedef struct {
    u16 usTag;/*0xEEEE*/
    u16 usBackupGpt;/*0:no backup,1:has backup*/
    u16 usEntryCount;
    u64 entryDataSize[32];
} gpt_compact_info;
/* based on linux/include/genhd.h */
typedef struct {
    u8 boot_ind;        /* 0x80 - active */
    u8 head;        /* starting head */
    u8 sector;        /* starting sector */
    u8 cyl;            /* starting cylinder */
    u8 sys_ind;        /* What partition type */
    u8 end_head;        /* end head */
    u8 end_sector;        /* end sector */
    u8 end_cyl;        /* end cylinder */
    u32 start_sect;    /* starting sector counting from 0 */
    u32 nr_sects;    /* nr of sectors in partition */
} mbr_partition ;

/* based on linux/fs/partitions/efi.h */
typedef struct _gpt_header {
    u64 signature;                          //固定字符串“EFI PART”
    u32 revision;                           //GPT版本号
    u32 header_size;                        //主GPT头大小
    u32 header_crc32;                       //主GPT头的CRC32校验数据，注意不是累加和校验
    u32 reserved1;                          //保留位
    u64 my_lba;                             //主GPT头起始扇区号，LBA1
    u64 alternate_lba;                      //主GPT头备份位置扇区号 LBA-1
    u64 first_usable_lba;                   //GPT分区起始扇区号，LBA34
    u64 last_usable_lba;                    //GPT分区结束扇区号，LBA-34
    efi_guid_t disk_guid;                   //磁盘的GUID，唯一标识，这也意味着全硬盘复制是行不通的.
    u64 partition_entry_lba;                //分区表起始扇区号，LBA2
    u32 num_partition_entries;              //分区表项数目，MS强行给128
    u32 sizeof_partition_entry;             //每个分区表占用字节数，128
    u32 partition_entry_array_crc32;        //分区表CRC校验数据
} gpt_header;

typedef union _gpt_entry_attributes {
    struct {
        u64 required_to_function:1;
        u64 no_block_io_protocol:1;
        u64 legacy_bios_bootable:1;
        u64 reserved:45;
        u64 type_guid_specific:16;
    } fields;
    unsigned long long raw;
} gpt_entry_attributes;

#define PARTNAME_SZ    72
typedef struct _gpt_entry {
    efi_guid_t partition_type_guid;
    efi_guid_t unique_partition_guid;
    u64 starting_lba;
    u64 ending_lba;
    gpt_entry_attributes attributes;
    u16 partition_name[PARTNAME_SZ / sizeof(u16)];
} gpt_entry;

typedef struct _legacy_mbr {
    u8 boot_code[440];
    u32 unique_mbr_signature;
    u16 unknown;
    mbr_partition partition_record[4];
    u16 signature;
} legacy_mbr;
#pragma pack()
#endif    /* _GPT_H */
